package com.xnyzc.lhy.gateway.config;

import com.google.common.base.Strings;
import com.xnyzc.lhy.common.component.service.IGatewayService;
import com.xnyzc.lhy.common.entity.PangRoute;
import com.xnyzc.lhy.common.util.CheckUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lengleng
 * @date 2018/5/15
 * 动态路由实现
 */
@Slf4j
public class DynamicRouteLocator extends DiscoveryClientRouteLocator {
    private ZuulProperties properties;
    private IGatewayService gatewayService;

    public DynamicRouteLocator(String servletPath, DiscoveryClient discovery, ZuulProperties properties, ServiceInstance localServiceInstance,
                               IGatewayService gatewayService) {
        super(servletPath, discovery, properties, localServiceInstance);
        this.properties = properties;
        this.gatewayService = gatewayService;
    }

    /**
     * 重写路由配置
     * <p>
     * 1. properties 配置。
     * 2. eureka 默认配置。
     * 3. DB数据库配置。
     *
     * @return 路由表
     */
    @Override
    protected LinkedHashMap<String, ZuulProperties.ZuulRoute> locateRoutes() {
        LinkedHashMap<String, ZuulProperties.ZuulRoute> routesMap = new LinkedHashMap<>();
        //读取properties配置、eureka默认配置
        routesMap.putAll(super.locateRoutes());
        routesMap.putAll(locateRoutesFromDb());
        log.info("----> init route success");
        LinkedHashMap<String, ZuulProperties.ZuulRoute> values = new LinkedHashMap<>();
        for (Map.Entry<String, ZuulProperties.ZuulRoute> entry : routesMap.entrySet()) {
            String path = entry.getKey();
            if (!path.startsWith("/")) {
                path = "/" + path;
            }
            if (!Strings.isNullOrEmpty(this.properties.getPrefix())) {
                path = this.properties.getPrefix() + path;
                if (!path.startsWith("/")) {
                    path = "/" + path;
                }
            }
            values.put(path, entry.getValue());
        }
        return values;
    }

    /**
     * Redis中保存的，避免启动链路依赖问题（取舍），网关依赖业务模块的问题
     *
     * @return
     */
    private Map<String, ZuulProperties.ZuulRoute> locateRoutesFromDb() {
        Map<String, ZuulProperties.ZuulRoute> routes = new LinkedHashMap<>();

        List<PangRoute> routeConfigs = gatewayService.getPangRouteList();

        if (CheckUtil.collectionIsEmpty(routeConfigs)) {
            return routes;
        }
        for (PangRoute result : routeConfigs) {
            if (CheckUtil.strIsEmpty(result.getRoute())) {
                continue;
            }
            result.setRoute(result.getRoute() + "/**");

            ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
            try {
                zuulRoute.setId(result.getSysCode());
                zuulRoute.setPath(result.getRoute());
                zuulRoute.setServiceId(result.getSysCode());
                zuulRoute.setRetryable(Boolean.TRUE);
                zuulRoute.setStripPrefix(Boolean.TRUE);
                zuulRoute.setUrl(new String());
            }
            catch (Exception e) {
                log.error("从数据库加载路由配置异常", e);
            }
            // 不进行忽略header信息的传递
            zuulRoute.setCustomSensitiveHeaders(true);

            log.info("添加数据库自定义的路由配置,path：{}，serviceId:{}", zuulRoute.getPath(), zuulRoute.getServiceId());
            routes.put(zuulRoute.getPath(), zuulRoute);
        }

        return routes;
    }
}
